package member

import (
	"bytes"
	"errors"
	"fmt"
	"math"
	"net/http"
	"parking-lot-go-dingding/config"
	"parking-lot-go-dingding/controller"
	"parking-lot-go-dingding/model"
	"parking-lot-go-dingding/model/cars"
	"parking-lot-go-dingding/model/dingtalk/system"
	"parking-lot-go-dingding/model/view"
	"strings"
	"time"

	"gorm.io/gorm"
)

type MemberStruct struct {
	Id           int       `json:"id" gorm:"type:int(10) unsigned auto_increment; NOT NULL; primary_key"`
	Mobile       string    `json:"mobile" gorm:"type:varchar(20); COMMENT:'手机号码'"`
	Type         int       `json:"type" gorm:"type:int(11); NOT NULL; COMMENT:'会员类型 1固定会员 2临时停车'"`
	RealName     string    `json:"real_name" gorm:"type:varchar(20); COMMENT:'会员名称'"`
	Avatar       string    `json:"avatar" gorm:"type:varchar(255); COMMENT:'头像'"`
	ExpiresTime  time.Time `json:"expires_time" gorm:"type:varchar(20); COMMENT:'过期时间'"`
	Remarks      string    `json:"remarks" gorm:"type:varchar(100); COMMENT:'备注'"`
	State        int       `json:"state" gorm:"type:tinyint(1); COMMENT:'账号状态 1正常 2禁用 3过期'"`
	AccountType  int       `json:"account_type" gorm:"type:tinyint(1); COMMENT:'账号类型 1钉钉 2微信'"`
	AccountExtId int       `json:"account_ext_id" gorm:"type:int(11); COMMENT:'账号扩展id'"`
	CreatedAt    time.Time `json:"created_at" gorm:"type:datetime"`
	UpdatedAt    time.Time `json:"updated_at" gorm:"type:datetime"`
	Money        float64   `json:"money" gorm:"type:decimal(10,2); COMMENT:'可用余额'"`
	IsVip        int       `json:"is_vip" gorm:"type:tinyint(1); COMMENT:'是否vip 1是 0否'"`
}

// 车牌号
func (c *MemberStruct) TableName() string {
	return "member"
}

func (c *MemberStruct) FirstByMobile(mobile string) (MemberStruct, error) {
	var memberStruct MemberStruct
	db := model.Db
	if err := db.
		Table(c.TableName()).
		Where("mobile = ?", mobile).
		First(&memberStruct).
		Error; err != nil {
		return memberStruct, err
	}
	return memberStruct, nil
}

// 修改会员
func (c *MemberStruct) DingTalkUpdate(memberData MemberStruct, carInfoList, carNumberList []string, carTypeList, carNoColorList []int, expTime, corpid string, money, nowCorpMoney float64) error {

	var err error
	tx := model.Db.Begin()

	//查询当前会员信息
	var membersDingtalkViewStruct view.MembersDingtalkViewStruct
	memberFind, err := membersDingtalkViewStruct.First(map[string]interface{}{
		"member_id": memberData.Id,
	})
	if err != nil {
		tx.Rollback()
		return err
	}

	//更新会员信息
	if err = tx.Debug().Table(c.TableName()).Where("id", memberData.Id).Updates(&memberData).Error; err != nil {
		tx.Rollback()
		return err
	}

	//删除不存在的车辆
	var carsStruct cars.CarsStruct
	if err = tx.Debug().Table(carsStruct.TableName()).Where("member_id = ? AND car_number NOT IN (?)", memberData.Id, carNumberList).Delete(&carsStruct).Error; err != nil {
		tx.Rollback()
		return err
	}

	//更新车辆信息
	expUnix, _ := time.Parse("2006-01-02 15:04", expTime)
	for k, _ := range carInfoList {
		//查询车辆
		var carsStruct cars.CarsStruct
		if err = tx.Table(carsStruct.TableName()).Where(map[string]interface{}{"member_id": memberData.Id, "car_number": carNumberList[k]}).First(&carsStruct).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
			tx.Rollback()
			return err
		}

		if !errors.Is(err, gorm.ErrRecordNotFound) {
			if err = tx.Debug().Table(carsStruct.TableName()).
				Where("member_id", memberData.Id).
				Where("car_number", carNumberList[k]).
				Updates(map[string]interface{}{
					"car_info":     carInfoList[k],
					"car_type":     carTypeList[k],
					"car_no_color": carNoColorList[k],
					"end_time":     int(expUnix.Unix()),
					"updated_at":   time.Now(),
				}).Error; err != nil {
				tx.Rollback()
				return err
			}
		} else {
			if err = tx.Debug().Table(carsStruct.TableName()).Create(&cars.CarsStruct{
				TripartiteType:    3,
				TripartiteVoucher: corpid,
				MemberId:          memberData.Id,
				Mobile:            memberData.Mobile,
				CarNumber:         carNumberList[k],
				CarInfo:           carInfoList[k],
				CarType:           carTypeList[k],
				CarNoColor:        carNoColorList[k],
				BindType:          2,
				StartTime:         int(time.Now().Unix()),
				EndTime:           int(expUnix.Unix()),
				CreatedAt:         time.Now(),
				UpdatedAt:         time.Now(),
			}).Error; err != nil {
				tx.Rollback()
				return err
			}
		}

		//绑定车牌异步请求
		seeting := controller.GetSetting()
		if seeting {
			go func() {
				//拼接url
				systemSection := config.Cfg.Section("SYSTEM")
				url := systemSection.Key("INTERFACE_URL").String() + "artificial/bind"

				jsonData := []byte(
					fmt.Sprintf(`{"phone": "%s", "car_id": "%s", "car_no_color": "%d", "car_type": "%d","park_type":"%d","type":"%d","start_time":"%s","end_time":"%s"}`,
						memberData.Mobile, carNumberList[k], carNoColorList[k], carTypeList[k], 1, 2, time.Now().Format("2006-01-02 15:04:05"), expTime+":00"))

				//发送请求
				resp, _ := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
				defer resp.Body.Close()
			}()
		}
	}

	if money != memberFind.MemberMoney {
		var changeType int
		var AfterMoney float64

		changeMoney := math.Abs(money - memberFind.MemberMoney)
		//增加用户余额
		if money > memberFind.MemberMoney {
			//扣除大账户余额
			var dingtalkSystemCorpStruct system.DingtalkSystemCorpStruct
			if err = tx.Table(dingtalkSystemCorpStruct.TableName()).Where("corp_id", corpid).Where("money > 0").UpdateColumn("money", gorm.Expr("money - ?", changeMoney)).Error; err != nil {
				tx.Rollback()
				return err
			}

			changeType = 2
			AfterMoney = nowCorpMoney - changeMoney
		} else { //减少用户余额
			//增加大账户余额
			var dingtalkSystemCorpStruct system.DingtalkSystemCorpStruct
			if err = tx.Table(dingtalkSystemCorpStruct.TableName()).Where("corp_id", corpid).Where("money > 0").UpdateColumn("money", gorm.Expr("money + ?", changeMoney)).Error; err != nil {
				tx.Rollback()
				return err
			}

			changeType = 1
			AfterMoney = nowCorpMoney + changeMoney
		}

		//会员类型
		memberType := "固定"
		if memberData.Type == 2 {
			memberType = "临时"
		}

		//余额变动记录
		var dingtalkSystemCorpMoneyLogStruct system.DingtalkSystemCorpMoneyLogStruct
		if err = tx.Debug().Table(dingtalkSystemCorpMoneyLogStruct.TableName()).Create(&system.DingtalkSystemCorpMoneyLogStruct{
			CorpId:        corpid,
			Type:          changeType,
			MemberId:      memberFind.MemberId,
			RealName:      memberFind.MemberRealName,
			Mobile:        memberFind.MemberMobile,
			Cars:          strings.Join(carNumberList, ","),
			Money:         changeMoney,
			OperationType: 2,
			Desc:          fmt.Sprintf("修改%s会员id:%d,手机号:%s,姓名:%s,当前余额:%f,修改后余额:%f", memberType, memberFind.MemberId, memberFind.MemberMobile, memberFind.MemberRealName, memberFind.MemberMoney, money),
			BeforeMoney:   nowCorpMoney,
			AfterMoney:    AfterMoney,
		}).Error; err != nil {
			tx.Rollback()
			return err
		}

	}

	tx.Commit()
	return nil
}

// 添加会员
func (c *MemberStruct) DingTalkCreate(memberData MemberStruct, memberDingtalkData MemberDingtalkStruct, carInfoList, carNumberList []string, carTypeList, carNoColorList []int, expTime, corpid string, money, nowMoney float64) error {

	var err error
	tx := model.Db.Begin()

	//插入钉钉会员
	var memberDingtalkStruct MemberDingtalkStruct
	if err := tx.Table(memberDingtalkStruct.TableName()).Debug().Create(&memberDingtalkData).Error; err != nil {
		tx.Rollback()
		return err
	}

	//插入会员信息
	memberData.AccountExtId = memberDingtalkData.Id
	if err := tx.Table(c.TableName()).Create(&memberData).Error; err != nil {
		tx.Rollback()
		return err
	}

	//插入车辆信息
	expUnix, _ := time.Parse("2006-01-02 15:04", expTime)
	var carsStruct cars.CarsStruct
	for k, _ := range carInfoList {
		if err = tx.Table(carsStruct.TableName()).Create(&cars.CarsStruct{
			TripartiteType:    3,
			TripartiteVoucher: corpid,
			MemberId:          memberData.Id,
			Mobile:            memberData.Mobile,
			CarNumber:         carNumberList[k],
			CarInfo:           carInfoList[k],
			CarType:           carTypeList[k],
			CarNoColor:        carNoColorList[k],
			BindType:          2,
			StartTime:         int(time.Now().Unix()),
			EndTime:           int(expUnix.Unix()),
			CreatedAt:         time.Now(),
			UpdatedAt:         time.Now(),
		}).Error; err != nil {
			tx.Rollback()
			return err
		}

		//绑定车牌异步请求
		seeting := controller.GetSetting()
		if seeting {
			//拼接url
			go func() {
				systemSection := config.Cfg.Section("SYSTEM")
				url := systemSection.Key("INTERFACE_URL").String() + "artificial/bind"

				jsonData := []byte(
					fmt.Sprintf(`{"phone": "%s", "car_id": "%s", "car_no_color": "%d", "car_type": "%d","park_type":"%d","type":"%d","start_time":"%s","end_time":"%s","much_type":"dingding"}`,
						memberData.Mobile, carNumberList[k], carNoColorList[k], carTypeList[k], 1, 2, time.Now().Format("2006-01-02 15:04:05"), expTime+":00"))

				//发送请求
				resp, _ := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
				defer resp.Body.Close()
			}()
		}
	}

	//余额变动
	var dingtalkSystemCorpStruct system.DingtalkSystemCorpStruct
	if err = tx.Table(dingtalkSystemCorpStruct.TableName()).Where("corp_id", corpid).Where("money > 0").UpdateColumn("money", gorm.Expr("money - ?", money)).Error; err != nil {
		tx.Rollback()
		return err
	}

	//会员类型
	memberType := "固定"
	if memberData.Type == 2 {
		memberType = "临时"
	}

	//余额变动记录
	var dingtalkSystemCorpMoneyLogStruct system.DingtalkSystemCorpMoneyLogStruct
	if err = tx.Table(dingtalkSystemCorpMoneyLogStruct.TableName()).Create(&system.DingtalkSystemCorpMoneyLogStruct{
		CorpId:        corpid,
		Type:          2,
		Money:         money,
		MemberId:      memberData.Id,
		RealName:      memberData.RealName,
		Mobile:        memberData.Mobile,
		OperationType: 1,
		Cars:          strings.Join(carNumberList, ","),
		Desc:          fmt.Sprintf("开通%s会员id:%d,手机号%s,姓名%s,金额%.2f", memberType, memberData.Id, memberData.Mobile, memberData.RealName, money),
		BeforeMoney:   nowMoney,
		AfterMoney:    nowMoney - money,
	}).Error; err != nil {
		tx.Rollback()
		return err
	}

	tx.Commit()
	return nil
}

// 删除会员
func (c *MemberStruct) DingTalkDelete(id int) error {

	var err error
	tx := model.Db.Begin()

	//查询会员信息
	var memberembersDingtalkViewStruct view.MembersDingtalkViewStruct
	memberFind, err := memberembersDingtalkViewStruct.First(map[string]interface{}{
		"member_id": id,
	})
	if err != nil {
		return err
	}

	//企业查询
	var dingtalkSystemCorpStruct system.DingtalkSystemCorpStruct
	dingtalkSystemCorp, err := dingtalkSystemCorpStruct.First(memberFind.MemberDingtalkCorpid)
	if err != nil {
		return err
	}

	//余额变动记录
	var dingtalkSystemCorpMoneyLogStruct system.DingtalkSystemCorpMoneyLogStruct
	if err = tx.Table(dingtalkSystemCorpMoneyLogStruct.TableName()).Create(&system.DingtalkSystemCorpMoneyLogStruct{
		CorpId:        memberFind.MemberDingtalkCorpid,
		Type:          2,
		Money:         memberFind.MemberMoney,
		MemberId:      memberFind.MemberId,
		RealName:      memberFind.MemberRealName,
		Mobile:        memberFind.MemberMobile,
		OperationType: 3,
		Desc:          fmt.Sprintf("删除%s会员id:%d,手机号%s,姓名%s,金额%.2f", memberFind.MemberType, memberFind.MemberId, memberFind.MemberMobile, memberFind.MemberRealName, memberFind.MemberMoney),
		BeforeMoney:   dingtalkSystemCorp.Money,
		AfterMoney:    dingtalkSystemCorp.Money + memberFind.MemberMoney,
	}).Error; err != nil {
		tx.Rollback()
		return err
	}

	var carsStruct cars.CarsStruct
	cars, err := carsStruct.List(map[string]interface{}{
		"member_id": id,
	})
	if err != nil {
		tx.Rollback()
		return err
	}

	//解除车牌异步请求
	seeting := controller.GetSetting()
	if seeting {
		for _, v := range cars {
			go func() {
				//	拼接url
				systemSection := config.Cfg.Section("SYSTEM")
				url := systemSection.Key("INTERFACE_URL").String() + "artificial/un_bind"

				jsonData := []byte(
					fmt.Sprintf(`{"phone": "%s", "car_id": "%s", "car_no_color": "%d", "car_type": "%d","much_type":"dingding"}`,
						v.Mobile, v.CarNumber, v.CarNoColor, v.CarType))

				//发送请求
				resp, _ := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
				defer resp.Body.Close()
			}()
		}
	}

	//余额回滚
	var dingtalkSystemCorpStructDescMoney system.DingtalkSystemCorpStruct
	if err = tx.Table(dingtalkSystemCorpStructDescMoney.TableName()).Debug().Where("corp_id", memberFind.MemberDingtalkCorpid).UpdateColumn("money", gorm.Expr("money + ?", memberFind.MemberMoney)).Error; err != nil {
		tx.Rollback()
		return err
	}

	//删除会员
	var memberStruct MemberStruct
	if err = tx.Table(c.TableName()).Where("id", id).Delete(&memberStruct).Error; err != nil {
		tx.Rollback()
		return err
	}

	//删除钉钉信息
	var memberDingtalkStruct MemberDingtalkStruct
	if err = tx.Table(memberDingtalkStruct.TableName()).Where("id", memberFind.MemberDingtalkId).Delete(&memberDingtalkStruct).Error; err != nil {
		tx.Rollback()
		return err
	}

	//删除车辆信息
	if err = tx.Table(carsStruct.TableName()).Where("member_id", id).Delete(&carsStruct).Error; err != nil {
		tx.Rollback()
		return err
	}

	tx.Commit()
	return nil
}

// 禁用 / 解禁
func (c *MemberStruct) DingTalkDisable(ids []int, state int) error {
	if err := model.Db.Debug().Table(c.TableName()).Where("id in ?", ids).Updates(map[string]interface{}{
		"state": state,
	}).Error; err != nil {
		return err
	}
	return nil
}
